package com.glsc.ngateway.platform.service.itflow.flowstrategy.cmdb.partStandardModify;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.glsc.ngateway.common.api.flowable.dto.FlowFormNewCPUStandardDetailDto;
import com.glsc.ngateway.common.api.flowable.dto.FlowFormNewDiskStandardDetailDto;
import com.glsc.ngateway.common.api.flowable.dto.FlowFormNewMemoryStandardDetailDto;
import com.glsc.ngateway.common.api.flowable.dto.FlowFormNewPartStandardDetailDto;
import com.glsc.ngateway.common.api.flowable.dto.task.doTaskParam.AbstractFlowSearchParamDto;
import com.glsc.ngateway.common.api.flowable.dto.task.formData.cmdb.PartStandardModifyTaskFormDto;
import com.glsc.ngateway.common.api.flowable.dto.task.formData.cmdb.domainDto.FlowFormPartStandardModifyDto;
import com.glsc.ngateway.common.api.platform.dto.user.PlatformUserDto;
import com.glsc.ngateway.common.base.converter.platform.*;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.flow.cmdb.*;
import com.glsc.ngateway.common.base.enums.itflow.ITFlowEnum;
import com.glsc.ngateway.common.base.enums.itflow.ITFlowTaskEnum;
import com.glsc.ngateway.common.base.enums.itflow.ITFlowTaskParamEnum;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.flow.cmdb.*;
import com.glsc.ngateway.common.base.utils.CollectionBuilder;
import com.glsc.ngateway.platform.service.itflow.flowstrategy.AbstractItFlowStrategy;
import com.glsc.ngateway.platform.service.itflow.flowstrategy.cmdb.partStandardModify.taskPostHandler.IPartStandardModifyTaskPostHandlerAudit;
import com.glsc.ngateway.platform.utils.AssertOverride;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhengyr
 * @date 2023/8/2-15:22
 */
@Component
public class PartStandardModifyFlowStrategy extends AbstractItFlowStrategy<FlowFormPartStandardModifyDto, PartStandardModifyTaskFormDto> {
    private Map<String, IPartStandardModifyTaskPostHandlerAudit> taskPostHandlerMap;
    private HashMap<String, String> modifyTypeMap = new HashMap<>();
    private final String ADDTYPE = "0";
    private final String DELETETYPE = "1";
    @Autowired
    FlowFormPartStandardModifyRepo flowFormPartStandardModifyRepo;
    @Autowired
    FlowFormNewCPUStandardDetailRepo cpuStandardNewRepo;
    @Autowired
    FlowFormNewMemoryStandardDetailRepo memoryStandardNewRepo;
    @Autowired
    FlowFormNewDiskStandardDetailRepo diskStandardNewRepo;
    @Autowired
    FlowFormNewPartStandardDetailRepo partStandardNewRepo;

    @Autowired
    public void setTaskPostHandlerMap(List<IPartStandardModifyTaskPostHandlerAudit> taskPostHandlerList) {
        this.taskPostHandlerMap = taskPostHandlerList.stream()
                .collect(Collectors.toMap(IPartStandardModifyTaskPostHandlerAudit::getTaskDefinitionKey, handler -> handler));
    }

    @Autowired
    private void setModifyTypeMap() {
        this.modifyTypeMap.put(ADDTYPE, "新增");
        this.modifyTypeMap.put(DELETETYPE, "删除");
    }

    @Override
    protected Map getTaskPassMap() {
        return taskPostHandlerMap;
    }

    @Override
    protected Map getTaskRejectMap() {
        return taskPostHandlerMap;
    }

    @Override
    public ITFlowEnum getFlowEnum() {
        return ITFlowEnum.CMDB_PART_STANDARD_MODIFY;
    }

    @Override
    public List<String> pageProcessId(AbstractFlowSearchParamDto param, Pageable pageable) {
        return null;
    }

    @Override
    public PartStandardModifyTaskFormDto saveOrUpdateForm(PartStandardModifyTaskFormDto flowableForm) throws Exception {
        if (StrUtil.isEmpty(flowableForm.getProcessId())) {
            throw PlatformException.error("没有流程processId,无法保存流程数据", false, false);
        }
        //保存流程主表单数据
        FlowFormPartStandardModify oldData = flowFormPartStandardModifyRepo.findByProcessId(flowableForm.getProcessId());
        if (Objects.nonNull(oldData)) {
            flowableForm.getFormMainData().setId(oldData.getId());
        }
        flowFormPartStandardModifyRepo.save(Objects.requireNonNull(FlowFormPartStandardModifyConverter.dto2Do(flowableForm.getFormMainData())));
        //操作类型
        String modifyType = flowableForm.getFormMainData().getModifyType();
        //配件类型
        String partType = flowableForm.getFormMainData().getPartType();
        if (Objects.equals(modifyType, ADDTYPE)) {
            //保存新增的cpu/内存/硬盘/配件数据到流程表单子表。先删除已有processId的全部数据，再插入
            saveStandardList(flowableForm.getProcessId(), flowableForm, partType, ADDTYPE);
        } else if (Objects.equals(modifyType, DELETETYPE)) {
            //业务类型是删除。先删除已有processId的全部数据，再插入
            saveStandardList(flowableForm.getProcessId(), flowableForm, partType, DELETETYPE);
        }
        return flowableForm;
    }

    @Override
    public PartStandardModifyTaskFormDto findFormByProcessId(String processId) {
        PartStandardModifyTaskFormDto flowableForm = new PartStandardModifyTaskFormDto();
        FlowFormPartStandardModify formMainDataDo = flowFormPartStandardModifyRepo.findByProcessId(processId);
        if (Objects.isNull(formMainDataDo)) {
            flowableForm.setFormMainData(new FlowFormPartStandardModifyDto());
        } else {
            flowableForm.setFormMainData(FlowFormPartStandardModifyConverter.do2Dto(formMainDataDo));
            if (Objects.equals(formMainDataDo.getModifyType(), ADDTYPE)) {
                //新增
                setFlowableStandardList(processId, flowableForm, formMainDataDo, ADDTYPE);
            } else if (Objects.equals(formMainDataDo.getModifyType(), DELETETYPE)) {
                //删除，从配件数据库里查到被删除的数据，返回给前端展示
                setFlowableStandardList(processId, flowableForm, formMainDataDo, DELETETYPE);
            }
        }
        return flowableForm;
    }

    /**
     * 从流程子表取数据返回给前端
     */
    private void setFlowableStandardList(String processId, PartStandardModifyTaskFormDto flowableForm, FlowFormPartStandardModify formMainDataDo, String modifyType) {
        switch (formMainDataDo.getPartType()) {
            case "cpu": {
                flowableForm.setCpuStandardNewDataList(
                        FlowFormNewCPUStandardDetailConverter.do2Dto(
                                cpuStandardNewRepo.findAllByprocessId(processId)
                        )
                );
                break;
            }
            case "memory": {
                flowableForm.setMemoryStandardNewDataList(
                        FlowFormNewMemoryStandardDetailConverter.do2Dto(
                                memoryStandardNewRepo.findAllByprocessId(processId)
                        )
                );
                break;
            }
            case "disk": {
                flowableForm.setDiskStandardNewDataList(
                        FlowFormNewDiskStandardDetailConverter.do2Dto(
                                diskStandardNewRepo.findAllByprocessId(processId)
                        )
                );
                break;
            }
            case "part": {
                flowableForm.setPartStandardNewDataList(
                        FlowFormNewPartStandardDetailConverter.do2Dto(
                                partStandardNewRepo.findAllByprocessId(processId)
                        )
                );
            }
            default:
        }
    }

    /**
     * 前端规格数据保存到流程子表
     *
     * @throws Exception
     */
    private void saveStandardList(String processId, PartStandardModifyTaskFormDto flowableForm, String partType, String modifyType) throws Exception {
        switch (partType) {
            case "cpu": {
                AssertOverride.notNull(flowableForm.getCpuStandardNewDataList(), "cpu规格异常：数据不能为空。");

                cpuStandardNewRepo.deleteAll(cpuStandardNewRepo.findAllByprocessId(processId));
                List<FlowFormNewCPUStandardDetailDto> collect = flowableForm.getCpuStandardNewDataList().stream().map(h -> {
                    h.setId(null);
                    h.setProcessId(flowableForm.getProcessId());
                    h.setModifyType(modifyType);
                    return h;
                }).collect(Collectors.toList());
                cpuStandardNewRepo.saveAll(FlowFormNewCPUStandardDetailConverter.dto2Do(collect));
                break;
            }
            case "memory": {
                AssertOverride.notNull(flowableForm.getMemoryStandardNewDataList(), "内存规格异常：数据不能为空。");
                memoryStandardNewRepo.deleteAll(memoryStandardNewRepo.findAllByprocessId(processId));
                List<FlowFormNewMemoryStandardDetailDto> collect = flowableForm.getMemoryStandardNewDataList().stream().map(h -> {
                    h.setId(null);
                    h.setProcessId(flowableForm.getProcessId());
                    h.setModifyType(modifyType);
                    return h;
                }).collect(Collectors.toList());
                memoryStandardNewRepo.saveAll(FlowFormNewMemoryStandardDetailConverter.dto2Do(collect));
                break;
            }
            case "disk": {
                AssertOverride.notNull(flowableForm.getDiskStandardNewDataList(), "硬盘规格异常：数据不能为空。");
                List<FlowFormNewDiskStandardDetailDto> collect = flowableForm.getDiskStandardNewDataList().stream().map(h -> {
                    h.setId(null);
                    h.setProcessId(flowableForm.getProcessId());
                    h.setModifyType(modifyType);
                    return h;
                }).collect(Collectors.toList());
                diskStandardNewRepo.deleteAll(diskStandardNewRepo.findAllByprocessId(processId));
                diskStandardNewRepo.saveAll(FlowFormNewDiskStandardDetailConverter.dto2Do(collect));
                break;
            }
            case "part": {
                AssertOverride.notNull(flowableForm.getPartStandardNewDataList(), "配件规格异常：数据不能为空。");
                List<FlowFormNewPartStandardDetailDto> collect = flowableForm.getPartStandardNewDataList().stream().map(h -> {
                    h.setId(null);
                    h.setProcessId(flowableForm.getProcessId());
                    h.setModifyType(modifyType);
                    return h;
                }).collect(Collectors.toList());
                partStandardNewRepo.deleteAll(partStandardNewRepo.findAllByprocessId(processId));
                partStandardNewRepo.saveAll(FlowFormNewPartStandardDetailConverter.dto2Do(collect));
                break;
            }
            default:
                throw PlatformException.error(modifyTypeMap.get(modifyType) + "配件规格异常");
        }
    }

    /**
     * 流程节点，发起时动态指定节点处理人
     */
    @Override
    protected Map<String, List<String>> initDefaultTaskUserGroup(PlatformUserDto creator) throws PlatformException {
        Map<String, List<String>> taskAssignee = new HashMap<>(16);
        //1、发起人
        taskAssignee.put(ITFlowTaskParamEnum.CMDB_PART_STANDARD_MODIFY_FLOW_BEGIN_TASK_ASSIGNMENTS.getName(), Arrays.asList(creator.getUsername()));
        //2、发起人确认
        taskAssignee.put(ITFlowTaskParamEnum.CMDB_PART_STANDARD_MODIFY_FLOW_CREATOR_AUDIT_TASK_ASSIGNMENTS.getName(), Arrays.asList(creator.getUsername()));
        return taskAssignee;
    }

}
